package huanzhao.erp.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import huanzhao.erp.domain.annotation.AvoidClear;
import huanzhao.erp.domain.annotation.CheckAssignable;
import huanzhao.erp.domain.annotation.CheckPosition;
import huanzhao.erp.domain.annotation.CheckTask;
import huanzhao.erp.domain.entity.Exception;
import huanzhao.erp.domain.po.Result;
import huanzhao.erp.domain.types.DeptPositionType;
import huanzhao.erp.domain.types.StaffType;
import huanzhao.erp.domain.types.TaskType;
import huanzhao.erp.domain.vo.ClearRecordVO;
import huanzhao.erp.domain.vo.ClearVO;
import huanzhao.erp.domain.vo.FinanceSettlementVO;
import huanzhao.erp.domain.vo.PhoneVO;
import huanzhao.erp.service.*;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Range;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * @author April
 * 2024/10/2 09:25
 * @version 1.0
 */
@RestController
@Slf4j
@Validated
@RequestMapping("/api/process")
public class SideProcessController {
    private final TaskService taskService;
    private final MiscService miscService;
    private final BasicService basicService;
    private final ClearService clearService;
    private final PhoneService phoneService;

    public SideProcessController(TaskService taskService, MiscService miscService, BasicService basicService, ClearService clearService, PhoneService phoneService) {
        this.taskService = taskService;
        this.miscService = miscService;
        this.basicService = basicService;
        this.clearService = clearService;
        this.phoneService = phoneService;
    }

    /**
     * 手动添加手机信息
     *
     * @return Result<?>
     * 2024/10/8 16:37:45
     */
    @PostMapping("phone")
    @AvoidClear
    @CheckPosition({DeptPositionType.WAREHOUSER, DeptPositionType.PURCHASER})
    public Result<?> addPhone(@RequestBody PhoneVO phone) {
        return Result.ok();
    }

    /**
     * 转调任务
     *
     * @param taskId  待转调的任务id
     * @param staffId 转调的任务接收人id
     * @return Result<?>
     * 2024/10/2 13:17:33
     */
    @PutMapping("reassign")
    public Result<?> reassignTask(@RequestParam long taskId, @RequestParam @CheckAssignable long staffId) {
        return taskService.reassignTask(taskId, staffId);
    }


    /**
     * 报告异常
     * <p>
     * 异常类型为损坏时，交给直属上级，直属上级可以选择维修或忽略。
     * 若选择维修，则由维修组长选择是否报损。
     * 为接收超时时，直属上级只能已读。
     * 为丢失时，交给业务经理审核。
     * 只有维修任务可以选择报损，选择报损后，交给维修组长审核
     *
     * @param type         0->接收超时，1->损坏，2->丢失，3->报损
     * @param reason       超时原因或损坏程度或丢失备注
     * @param discoverTime 发现日期（当为丢失时）
     * @return Result<?>
     * 2024/10/8 16:15:17
     */
    @PostMapping("exception/report")
    public Result<?> reportException(@RequestParam @CheckTask(completable = false) long taskId, @RequestParam @Range(max = 3) int type, @RequestParam @NotBlank String reason, @RequestParam(required = false) @Past Date discoverTime) {
        return miscService.reportException(taskId, type, reason, discoverTime);
    }

    /**
     * 处理异常
     * <p>
     * 是否批准，对于超时，只能为是；
     * 对于损坏，是代表送维修，否代表忽略；
     * 对于丢失，是代表确认丢失，否代表找到了；
     * 对于报损，是代表确认报损，否代表忽略报损，确认报损时若当前操作人为维修组长，则继续上报到业务经理，若已经为业务经历，则手机报损。
     * 员工报告损坏、丢失、报损三种情况时，原任务转化到异常状态，当领导处理时选择否，原任务恢复执行状态。
     *
     * @param exceptionId 异常事务id
     * @param approve     是否批准
     * @param response    批复
     * @return Result<?>
     * 2024/10/8 16:15:52
     */
    @PostMapping("exception/handle")
    public Result<?> handleException(@RequestParam long exceptionId, @RequestParam boolean approve, @RequestParam @NotBlank String response) {
        return miscService.handleException(exceptionId, approve, response);
    }

    /**
     * 查询异常单
     *
     * @param type    异常事务类型：0->接收超时，1->损坏，2->丢失，3->报损
     * @param approve 异常单是否通过审核
     * @param send    异常单的归属类型，为自己发出的还是自己收到的
     * @return Result<IPage < Exception>>
     * 2024/10/8 16:16:21
     */
    @GetMapping("exception")
    public Result<IPage<Exception>> getException(@RequestParam(required = false) @Range(max = 3) Integer type, @RequestParam(required = false) Boolean approve, @RequestParam boolean send, @RequestParam int pageNum, @RequestParam int pageSize) {

        return Result.ok();
    }

    /**
     * 查询盘库列表
     *
     * @param state 盘库的状态：0->所有盘库记录，1->正在进行的盘库，2->历史盘库记录
     * @return Result<List < ClearVO>>
     * 2024/10/8 16:16:49
     */
    @GetMapping("clear")
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<IPage<ClearVO>> getClearList(@RequestParam @Range(max = 2) int state, @RequestParam int pageNum, @RequestParam int pageSize) {
        return Result.ok(clearService.getClearList(state, pageNum, pageSize));
    }

    /**
     * 启动盘库
     *
     * @param big      是否为大盘库
     * @param imeiList 为小盘库时可用，本次盘库的手机imei列表
     * @return Result<?>
     * 2024/10/8 16:17:03
     */
    @PostMapping("clear")
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<?> startClear(@RequestParam boolean big, @RequestParam(required = false) @Size(min = 1) List<String> imeiList, @RequestParam(required = false) String comment) {
        return clearService.startClear(big, imeiList, comment);
    }

    /**
     * 盘点确认
     *
     * @return Result<?>
     * 2024/10/8 16:17:17
     */
    @PutMapping("clear/confirm")
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<?> confirmClear(@RequestParam @NotBlank String imei, @RequestParam long clearId) {
        return clearService.confirmClear(imei, clearId);
    }

    /**
     * 结束盘库
     *
     * @param clearId 需要结束的盘库id
     * @return Result<?>
     * 2024/10/8 16:17:25
     */
    @DeleteMapping("clear")
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<?> finishClear(@RequestParam long clearId) {
        return clearService.finishClear(clearId);
    }

    /**
     * 查询特定盘库记录中的手机
     *
     * @param found 手机是否已找到
     * @return 返回手机id数组
     * 2024/10/13 09:49:48
     */
    @GetMapping("clear/phone/{clearId}")
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<List<Long>> getClearPhones(@PathVariable long clearId, @RequestParam(required = false) Boolean found) {
        return clearService.getClearPhones(clearId, found);
    }

    /**
     * 查询特定盘库记录
     *
     * @return Result<ClearVO>
     * 2024/10/8 16:17:34
     */
    @GetMapping("clear/{clearId}")
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<ClearVO> getClearById(@PathVariable long clearId) {
        return clearService.getClearById(clearId);
    }

    /**
     * 查询手机的盘库记录
     *
     * @return Result<List < ClearRecordVO>>
     * 2024/10/8 16:17:41
     */
    @GetMapping("clear/phone")
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<List<ClearRecordVO>> getPhoneClearRecords(@RequestParam @NotBlank String imei) {
        return clearService.getPhoneClearRecords(imei);
    }

    /**
     * 录入待销售手机
     *
     * @return Result 返回没有录入成功的imei
     * 2024/10/8 16:17:47
     */
    @PostMapping("sale/enter")
    @AvoidClear
    @CheckPosition({DeptPositionType.WAREHOUSER, DeptPositionType.PURCHASER})
    public Result<Set<String>> enterPhoneForSale(@RequestParam @NotNull @Size(min = 1) List<String> imeiList, @RequestParam(required = false) String comment) {
        return phoneService.enterPhoneForSale(imeiList, comment);
    }

    /**
     * 仅出库
     *
     * @param imei         手机imei
     * @param warehouserId 执行销售发货的库管id
     * @return Result<?>
     * 2024/10/8 16:17:56
     */
    @PostMapping("sale/outbound")
    @AvoidClear
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<?> outboundOnly(@RequestParam @NotBlank String imei, @RequestParam @CheckAssignable(StaffType.WAREHOUSER) long warehouserId, @RequestParam(required = false) String comment) {
        return phoneService.outboundOnly(imei, warehouserId, comment);
    }

    /**
     * 销售发货
     *
     * @param waybill 发货运单号
     * @return Result<?>
     * 2024/10/8 16:18:12
     */
    @PostMapping("sale/ship")
    public Result<?> saleShip(@RequestParam @CheckTask(TaskType.SHIP_WHEN_SALE) long taskId, @RequestParam @NotBlank String waybill, @RequestParam(required = false) String comment) {
        return taskService.saleShip(taskId, waybill, comment);
    }

    /**
     * 录入退货手机
     *
     * @return Result<?>
     * 2024/10/8 16:18:32
     */
    @PostMapping("sale/return/enter")
    @AvoidClear
    @CheckPosition({DeptPositionType.WAREHOUSER, DeptPositionType.PURCHASER})
    public Result<Set<String>> enterReturnedPhone(@RequestParam @NotNull @Size(min = 1) List<String> imeiList, @RequestParam(required = false) String comment) {
        return phoneService.enterReturnedPhone(imeiList, comment);
    }

    /**
     * 客户退货
     * 该接口目前依据手机的上一个状态进行处理（当前的状态为：销售待退货），当上一个状态为：
     * 待销售、仅出库：触发未发货取回，需要重新入库
     * 销售收入待结算：触发退货签收，需要进行退货检查，并撤回相应的销售结算事务
     * 已售出：触发售后退货签收，需进行退货检查，并生成买家退货结算事务
     *
     * @param staffId 未发货取回是为库管id，其他情况为的采购id
     * @return Result<?>
     * 2024/10/8 16:18:37
     */
    @PostMapping("sale/return")
    @AvoidClear
    @CheckPosition({DeptPositionType.WAREHOUSER, DeptPositionType.PURCHASER})
    public Result<?> clientReturn(@RequestParam @NotBlank String imei,
                                  @RequestParam @CheckAssignable long staffId,
                                  @RequestParam(required = false) String waybill,
                                  @RequestParam(required = false) String comment) {
        return phoneService.clientReturn(imei, staffId, waybill, comment);
    }

    /**
     * 录入售后手机
     *
     * @return Result<?>
     * 2024/10/8 16:19:02
     */
    @PostMapping("aftersale/enter")
    @AvoidClear
    @CheckPosition({DeptPositionType.WAREHOUSER, DeptPositionType.PURCHASER})
    public Result<Set<String>> enterAftersalePhones(@RequestParam @NotNull @Size(min = 1) List<String> imeiList, @RequestParam(required = false) String comment) {
        return phoneService.enterAftersalePhones(imeiList, comment);
    }

    /**
     * 售后维修签收
     *
     * @param purchaserId 指定的采购员id
     * @return Result<?>
     * 2024/10/8 16:19:10
     */
    @PostMapping("aftersale/sign")
    @AvoidClear
    @CheckPosition(DeptPositionType.WAREHOUSER)
    public Result<?> signAftersalePhone(@RequestParam @NotBlank String imei,
                                        @RequestParam @CheckAssignable(StaffType.PURCHASER) long purchaserId,
                                        @RequestParam @NotBlank String waybill,
                                        @RequestParam(required = false) String comment) {
        return phoneService.signAftersalePhone(imei, purchaserId, waybill, comment);
    }

    /**
     * 接收售后
     *
     * @return Result<?>
     * 2024/10/8 16:19:24
     */
    @PostMapping("aftersale/receive")
    public Result<?> receiveAftersale(@RequestParam @CheckTask(TaskType.RECEIVE_AFTER_SALE) long taskId, @RequestParam(required = false) String comment) {
        return taskService.receiveAftersale(taskId, comment);
    }

    /**
     * 售后结束发货
     *
     * @return Result<?>
     * 2024/10/8 16:19:32
     */
    @PostMapping("aftersale/ship")
    public Result<?> shipAftersalePhone(@RequestParam @CheckTask(TaskType.SHIP_WHEN_AFTER_SALE_FINISHED) long taskId,
                                        @RequestParam @NotBlank String waybill,
                                        @RequestParam(required = false) String comment) {
        return taskService.shipAftersalePhone(taskId, waybill, comment);
    }

    /**
     * 按条件查询财务结算数据
     *
     * @param type    类型：0->维修成本结算、1->采购退货结算、2->买家退货结算、3->销售收入结算
     * @param confirm 是否已确认结算
     * @return Result<IPage < FinanceSettlementVO>>
     * 2024/10/8 16:19:40
     */
    @GetMapping("finance")
    @CheckPosition(DeptPositionType.FINANCER)
    public Result<IPage<FinanceSettlementVO>> getFinanceSettlements(@RequestParam(required = false) @Range(max = 3) Integer type, @RequestParam(required = false) Boolean confirm, @RequestParam int pageNum, @RequestParam int pageSize) {
        return Result.ok();
    }

    /**
     * 确认财务结算数据
     *
     * @param settlementId 结算id
     * @param price        修改结算金额，传输字符串
     * @return Result<?>
     * 2024/10/8 16:19:54
     */
    @PostMapping("finance")
    @CheckPosition(DeptPositionType.FINANCER)
    public Result<?> confirmFinanceSettlement(@RequestParam long settlementId, @RequestParam(required = false) BigDecimal price, @RequestParam(required = false) String comment) {
        return miscService.confirmFinanceSettlement(settlementId, price, comment);
    }
}
